#ifndef _DOMAIN_
#define _DOMAIN_

#include "Point.h"
#include <cassert>
/**
 * @brief Domain:定义域类
 *
 * @tparam int DIM [维度]
 */
template <unsigned int DIM>
class Domain
{
public:
    /**
     * @brief 默认构造函数
     */
    Domain() = default;
    /**
     * @brief 默认析构函数
     */
    virtual ~Domain() = default;
    /**
     * @brief 含参构造函数
     *
     * @param _vertexList 定义域边界的顶点，以逆时针顺序给出
     */
    Domain(std::vector<Point<DIM>> &_vertexList) : vertexList{_vertexList} {};
    /**
     * @brief 设置定义域边界的顶点
     *
     * @param _vertexList 定义域边界的顶点，以逆时针顺序给出
     */
    virtual void setVertexList(std::vector<Point<DIM>> &_vertexList) { vertexList = _vertexList; };
    virtual vector<Point<2>> &getVertexList() { return vertexList; }
    virtual void setVertex(int _i, const Point<DIM> &_vertex) { vertexList[_i] = _vertex; }
    /**
     * @brief 获取定义域边界第i个顶点
     *
     * @param _i 以逆时针顺序，顶点的下标
     * @return 第i个顶点
     */
    virtual Point<DIM> &getVertex(int _i) { return vertexList[_i]; };

protected:
    std::vector<Point<DIM>> vertexList; /*< 定义域的边界顶点*/
};

/**
 * @file   Domain.h
 * @author AOM
 * @date   Sat Mar  4 10:07:27 2023
 *
 * @brief  边界结构体，处理D氏边界条件
 *
 *
 */

template <unsigned int DIM>
struct Boundary
{
    std::vector<Point<DIM>> _segementpointlist;
    bool is_on_boundary(Point<DIM> point);
    void setsegment(std::vector<Point<DIM>> temp) { _segementpointlist = temp; };
    Boundary(){};
    Boundary(std::vector<Point<DIM>> temp) { _segementpointlist = temp; };
};

template <>
bool Boundary<2>::is_on_boundary(Point<2> point)
{
    double x1 = _segementpointlist[0][0];
    double y1 = _segementpointlist[0][1];
    double x2 = _segementpointlist[1][0];
    double y2 = _segementpointlist[1][1];
    double x = point[0];
    double y = point[1];
    if (x1 > x2) // 按照x从小到大
    {
        std::swap(x1, x2);
        std::swap(y1, y2);
    }
    bool ans = false;
    if (y1 == y2)
    {
        if (x >= x1 && x <= x2)
            ans = (y == y1);
    }
    else if (x1 == x2)
    {
        if (y2 > y1)
        {
            ans = ((x == x1) && (y >= y1 && y <= y2));
        }
        else
        {
            ans = ((x == x1) && (y >= y2 && y <= y1));
        }
    }
    return ans;
}

/**
 * @brief 二维矩形
 */
class Rectangle2D : public Domain<2>
{
public:
    /**
     * @brief 默认构造函数。
     *
     */
    Rectangle2D() = default;
    /**
     * @brief 默认析构函数。
     */
    ~Rectangle2D() = default;
    /**
     * @brief 含参构造函数
     *
     * @param pointList 定义域边界的顶点，以逆时针顺序给出
     */
    Rectangle2D(std::vector<Point<2>> &_vertexList)
    {
        assert(_vertexList.size() == 4);
        vertexList.resize(_vertexList.size());
        copy(_vertexList.begin(), _vertexList.end(), vertexList.begin());
    };
    /**
     * @brief 设置定义域边界的顶点
     *
     * @param _vertexList 定义域边界的顶点，以逆时针顺序给出
     */
    virtual void setVertexList(std::vector<Point<2>> &_vertexList)
    {
        assert(_vertexList.size() == 4);
        vertexList.resize(_vertexList.size());
        copy(_vertexList.begin(), _vertexList.end(), vertexList.begin());
    };
    virtual vector<Point<2>> &getVertexList()
    {
        return vertexList;
    }
    virtual void setVertex(int _i, const Point<2> &_vertex)
    {
        vertexList[_i] = _vertex;
    }

    /**
     * @brief 获取定义域边界第i个顶点
     *
     * @param _i 以逆时针顺序，顶点的下标
     * @return 第i个顶点
     */
    virtual Point<2> &getVertex(int _i)
    {
        return vertexList[_i];
    }
    /**
     *
     *
     *
     * @return 返回所有边界
     */
    std::vector<Boundary<2>> boundary()
    {
        std::vector<Boundary<2>> temp;
        for (int i = 0; i < 3; i++)
        {
            std::vector<Point<2>> p;
            p.push_back(vertexList[i]);
            p.push_back(vertexList[i + 1]);
            Boundary<2> b(p);
            temp.push_back(b);
        }
        std::vector<Point<2>> p4(2);
        p4[0] = vertexList[3];
        p4[1] = vertexList[0];
        temp.push_back(p4);
        return temp;
    }
};

#else
#endif
